package com.beyondsoft.mcms.web;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.roo.addon.web.mvc.controller.finder.RooWebFinder;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.beyondsoft.mcms.common.CommonUtils;
import com.beyondsoft.mcms.common.Constants;
import com.beyondsoft.mcms.domain.Category;
import com.beyondsoft.mcms.domain.Conference;
import com.beyondsoft.mcms.domain.Item;
import com.beyondsoft.mcms.reference.AuthRole;

@RequestMapping("/conferences")
@Controller
@RooWebScaffold(path = "conferences", formBackingObject = Conference.class)
@RooWebFinder
public class ConferenceController {

    @RequestMapping(params = "form", produces = "text/html")
    public String createForm(Model uiModel) {
        Conference conference = new Conference();
        conference.setRegistrationStartTime(new Date());
        conference.setCreateDate(new Date());
        conference.setCreatedBy(CommonUtils.getCurrentUsername());
        conference.setSponsor(Constants.CONFERENCE_DEFAULT_SPONSOR);
        conference.setOrganizer(Constants.CONFERENCE_DEFAULT_SPONSOR);
        conference.setConferenceStatus(Item.findItem(Constants.CONFERENCE_STATUS_NOADVICING));
        populateEditForm(uiModel, conference);
        return "conferences/create";
    }

    @RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(@Valid Conference conference, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors() || hasBindingDateError(conference, bindingResult)) {
            populateEditForm(uiModel, conference);
            return "conferences/create";
        }
        uiModel.asMap().clear();
        conferenceService.saveConference(conference);
        return "redirect:/conferences/" + encodeUrlPathSegment(conference.getId().toString(), httpServletRequest);
    }

    @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String update(@Valid Conference conference, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors() || hasBindingDateError(conference, bindingResult)) {
            populateEditForm(uiModel, conference);
            return "conferences/update";
        }
        uiModel.asMap().clear();
        conference.setUpdateDate(new Date());
        conference.setUpdatedBy(SecurityContextHolder.getContext().getAuthentication().getName());
        conferenceService.updateConference(conference);
        return "redirect:/conferences/" + encodeUrlPathSegment(conference.getId().toString(), httpServletRequest);
    }

    @RequestMapping(value = "/{id}", produces = "text/html")
    public String show(@PathVariable("id") Long id, Model uiModel) {
        addDateTimeFormatPatterns(uiModel);
        uiModel.addAttribute("conference", Conference.findConference(id));
        uiModel.addAttribute("itemId", id);
        AuthRole authority = CommonUtils.getCurrentRole();
        if (authority.equals(AuthRole.ORDINARY)) {
            return "conferences/ordinaryshow";
        } else return "conferences/show";
    }

    @RequestMapping(params = { "find=ByNameLikeAndConferenceTypeAndConferenceStatus", "form" }, method = RequestMethod.GET)
    public String findConferencesByNameLikeAndConferenceTypeAndConferenceStatusForm(Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.getSession().setAttribute("name", null);
        request.getSession().setAttribute("conferenceType", null);
        request.getSession().setAttribute("conferenceStatus", null);
        return findConferencesByNameLikeAndConferenceTypeAndConferenceStatus(null, null, null, uiModel);
    }

    @RequestMapping(params = "find=ByNameLikeAndConferenceTypeAndConferenceStatus", method = RequestMethod.GET)
    public String findConferencesByNameLikeAndConferenceTypeAndConferenceStatus(@RequestParam(value = "name", required = false) String name, @RequestParam(value = "conferenceType", required = false) Item conferenceType, @RequestParam(value = "conferenceStatus", required = false) Item conferenceStatus, Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String page = request.getParameter("page");
        String size = request.getParameter("size");
        int sizeNo = size == null ? 10 : Integer.valueOf(size);
        int pageNo = page == null ? 1 : Integer.valueOf(page);
        if (page != null && size != null) {
            name = (String) request.getSession().getAttribute("name");
            conferenceType = (Item) request.getSession().getAttribute("conferenceType");
            conferenceStatus = (Item) request.getSession().getAttribute("conferenceStatus");
        } else {
            request.getSession().setAttribute("name", name);
            request.getSession().setAttribute("conferenceType", conferenceType);
            request.getSession().setAttribute("conferenceStatus", conferenceStatus);
        }
        uiModel.addAttribute("name", name);
        uiModel.addAttribute("conferenceType", conferenceType);
        uiModel.addAttribute("conferenceStatus", conferenceStatus);
        return list(pageNo, sizeNo, uiModel);
    }

    @RequestMapping(produces = "text/html")
    public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        List<Item> conferenceTypes = Item.findItemsByCategoryAndIsValid(Category.findCategory(new Long(Constants.CONFERENCE_TYPE)), true).getResultList();
        uiModel.addAttribute("conferencetypes", conferenceTypes);
        List<Item> conferenceStatuses = Item.findItemsByCategoryAndIsValid(Category.findCategory(new Long(Constants.CONFERENCE_STATUS)), true).getResultList();
        uiModel.addAttribute("conferencestatuses", conferenceStatuses);
        String name = (String) uiModel.asMap().get("name");
        Item conferenceType = (Item) uiModel.asMap().get("conferenceType");
        Item conferenceStatus = (Item) uiModel.asMap().get("conferenceStatus");
        int sizeNo = size == null ? 10 : size.intValue();
        final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
        float nrOfPages = 0.0f;
        List<Conference> conferences = Conference.findConferencesByNameLikeAndConferenceTypeAndConferenceStatus(name, conferenceType, conferenceStatus).getResultList();
        AuthRole authority = CommonUtils.getCurrentRole();
        // if (authority.equals(AuthRole.ORDINARY)) {
        // List<Conference> advicedConferences =
        // Advice.findConferencesByMemberInfoAndConferenceStatus(CommonUtils.getCurrentMember(),
        // null).getResultList();
        // filterConferences(advicedConferences, conferences);
        // }
        int lastResult = (conferences.size() > (sizeNo + firstResult)) ? (sizeNo + firstResult) : conferences.size();
        nrOfPages = (float) conferences.size() / sizeNo;
        uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
        uiModel.addAttribute("conferences", conferences.subList(firstResult, lastResult));
        uiModel.addAttribute("selectQueryIds", (conferenceType == null ? -1 : conferenceType.getId()) + "," + (conferenceStatus == null ? -1 : conferenceStatus.getId()));
        uiModel.addAttribute("find", "ByNameLikeAndConferenceTypeAndConferenceStatus"); // differ
        // non-query
        // request
        addDateTimeFormatPatterns(uiModel);
        if (authority.equals(AuthRole.ORDINARY)) {
            return "conferences/ordinarylist";
        } else {
            return "conferences/list";
        }
    }

    @RequestMapping(value = "/{id}", params = "attchedDocuments", method = RequestMethod.GET)
    public String listDocuments(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest) {
        return "redirect:/documents/list/" + encodeUrlPathSegment(id.toString(), httpServletRequest);
    }

    @RequestMapping(value = "/{id}", params = "report", method = RequestMethod.GET)
    public String reportByConference(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest) {
        return "redirect:/advices/reportByConference?conference=" + encodeUrlPathSegment(id.toString(), httpServletRequest);
    }

    void populateEditForm(Model uiModel, Conference conference) {
        uiModel.addAttribute("conference", conference);
        addDateTimeFormatPatterns(uiModel);
        uiModel.addAttribute("conferencetypes", Item.findItemsByCategoryAndIsValid(Category.findCategory(new Long(Constants.CONFERENCE_TYPE)), true).getResultList());
        List<Item> conferencestatuses = Item.findItemsByCategoryAndIsValid(Category.findCategory(new Long(Constants.CONFERENCE_STATUS)), true).getResultList();
        filterConferenceStatuses(conference, conferencestatuses);
        uiModel.addAttribute("conferencestatuses", conferencestatuses);
    }

    private void filterConferences(List<Conference> advicedConferences, List<Conference> conferences) {
        for (int i = 0; i < conferences.size(); i++) {
            Conference conference = conferences.get(i);
            if (!advicedConferences.contains(conference)) {
                conferences.remove(conference);
                i--;
            }
        }
    }

    private void filterConferenceStatuses(Conference conference, List<Item> conferenceStatuses) {
        Item status = conference.getConferenceStatus();
        for (int i = 0; i < conferenceStatuses.size(); i++) {
            Item conferenceStatus = conferenceStatuses.get(i);
            if (conferenceStatus.getId() < status.getId()) {
                conferenceStatuses.remove(conferenceStatus);
                i--;
            }
        }
    }

    private Boolean hasBindingDateError(Conference conference, BindingResult bindingResult) {
        Date regStartDate = conference.getRegistrationStartTime();
        Date regEndDate = conference.getRegistrationEndTime();
        Date holdDate = conference.getHoldDate();
        if (conference.getId() == null) {
            String currentDate = new SimpleDateFormat("yy-MM-dd").format(new Date());
            String startDate = new SimpleDateFormat("yy-MM-dd").format(regStartDate);
            if (startDate.compareTo(currentDate) < 0) {
                bindingResult.rejectValue("registrationStartTime", "conference_field_start_date");
                return true;
            }
        }
        if (regEndDate.compareTo(regStartDate) < 0) {
            bindingResult.rejectValue("registrationEndTime", "conference_field_end_date");
            return true;
        }
        if (holdDate.compareTo(regEndDate) < 0) {
            bindingResult.rejectValue("holdDate", "conference_field_hold_date");
            return true;
        }
        return false;
    }
}
